<?php

class Base{
    public $dir;
    public $url;
    public $appid;
    public $appsecret;
    public $mch_id;
    //商户自定义key（签名用到）
    public $sign_key;
    //APIv3密钥
    public $aes_key;
    //私钥证书位置
    public $privateKeyPath;
    //证书存放位置
    public $sslCertPath;
    //包含公钥的解密后明文证书存放位置
    public $publicKeyPath;
    //证书完整响应体存放位置
    public $certDataPath;
    //身份证图片等上传临时保存路径
    public $uploadMediaPath;
    //申请完整响应体存放位置
    public $applyDataPath;
    //查询完整响应体存放位置
    public $queryDataPath;
    //绑定AppID完整相应体
    public $bindAppIDPath;

    public function __construct() {
        $this->dir=dirname(dirname(__FILE__));
        $this->url='https://'.$_SERVER['HTTP_HOST'];
        $this->appid='wx0f031xxx7eba20b';
        $this->appsecret='5e9544d1xxx8f381972cf79d7a4';
        $this->mch_id='1364xxx302';
        $this->sign_key='987654321098xxx9876543210Kk';
        $this->aes_key='98765432109xxxx2100123456789Kk';
        $this->privateKeyPath=$this->dir.'/libs/data/apiclient_key.pem';
        $this->sslCertPath=$this->dir.'/libs/data/apiclient_cert.pem';
        $this->publicKeyPath=$this->dir.'/libs/data/apiclient_public_key.pem';
        $this->certDataPath=$this->dir.'/libs/data/cert_data.json';
        $this->uploadMediaPath=$this->dir.'/assets/image';
        $this->applyDataPath=$this->dir.'/libs/data/apply_data.json';
        $this->queryDataPath=$this->dir.'/libs/data/query_data.json';
        $this->bindAppIDPath=$this->dir.'/libs/data/bind_appid_data.json';
    }

    //生成签名
    public function generateSign(array $data,$signType = 'HMAC-SHA256') {
        //签名步骤一：按字典序排序参数
        ksort($data);

        $string = $this->toUrlParams($data);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=" . $this->sign_key;

        //签名步骤三：MD5加密或者HMAC-SHA256
        if ($signType == 'MD5') {
            //如果签名小于等于32个,则使用md5验证
            $string = md5($string);
        } else {
            //是用sha256校验
            $string = hash_hmac("sha256", $string, $this->sign_key);
        }
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    //验签
    public function checkSign($data){
        if(strlen($data['sign']) <= 32){
            $_sign=$this->generateSign($data,'MD5');
        }else{
            $_sign=$this->generateSign($data);
        }
        if ($_sign == $data['sign']) {
            return true;
        }
        exit('验签失败');
    }


    //数组转xml
    public function arrayToXml($array=[]) {
        $xml = "<xml>";
        foreach ($array as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    //xml转数组
    public function xmlToArray($xml) {
        $xml_parser = xml_parser_create();
        if (!xml_parse($xml_parser, $xml, true)) {
            xml_parser_free($xml_parser);
            return false;
        } else {
            libxml_disable_entity_loader(true);
            return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        }
    }
    //curlRequest
    public function curlRequest($url, $data = '', array $headers = [], $userCert = false, $timeout = 30) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        //设置超时
        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
        if ($userCert) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);//严格校验
            curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLCERT, $this->sslCertPath);
            curl_setopt($curl, CURLOPT_SSLKEY, $this->privateKeyPath);
        } else {
            if (substr($url, 0, 5) == 'https') {
                curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
                curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
            }
        }
        if (!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output          = curl_exec($curl);
        $http_code       = curl_getinfo($curl, CURLINFO_HTTP_CODE);    // 获取响应状态码
        $error           = curl_error($curl);
        curl_close($curl);
        if ($http_code != 200) {
            exit("error:{$error}");
        }
        return $this->xmlToArray($output);
    }

    //媒体文件内容hash值
    public function hashMedia($path, $type = 'md5'){
        return hash_file($type, $path);
    }

    //格式化参数格式化成url参数
    protected function toUrlParams(array $data) {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v !== "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }

    //敏感信息加密
    public function publicKeyEncrypt($string) {
        $crypted   = '';
        $publicKey = file_get_contents($this->publicKeyPath);
        if ($publicKey) {
            $publicKeyResource = openssl_get_publickey($publicKey);
            $f                 = openssl_public_encrypt($string, $crypted, $publicKeyResource, OPENSSL_PKCS1_PADDING);
            openssl_free_key($publicKeyResource);
            if ($f) {
                return base64_encode($crypted);
            }
        }
        exit('公钥获取失败');
    }

    //获取客户端ip
    public function getClientIP() {
        $ip = getenv('HTTP_CLIENT_IP');
        if ($ip && strcasecmp($ip, 'unknown')) {
            return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : null;
        }

        $ip = getenv('HTTP_X_FORWARDED_FOR');
        if ($ip && strcasecmp($ip, 'unknown')) {
            return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : null;
        }

        $ip = getenv('REMOTE_ADDR');
        if ($ip && strcasecmp($ip, 'unknown')) {
            return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : null;
        }

        $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
        if ($ip && strcasecmp($ip, 'unknown')) {
            return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : null;
        }
        return null;
    }

    //判断是否微信端
    public function isWechatClient(){
        return strripos($_SERVER['HTTP_USER_AGENT'],'micromessenger')!=false;
    }

    //获取用户信息包含Openid
    public function getUserInfo(){
        $SERVER_NAME = $_SERVER['SERVER_NAME'];
        $REQUEST_URI = $_SERVER['REQUEST_URI'];
        //授权回调页面域名
        $redirect_uri = urlencode('http://' . $SERVER_NAME . $REQUEST_URI);
        $code = $_GET['code'];
        if (!$code) {
            // 网页授权当scope=snsapi_userinfo时才会提示是否授权应用
            $autourl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
            header("location:$autourl");
        } else {
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->appsecret."&code=$code&grant_type=authorization_code";
            $response = $this->curlRequest($url);
            return $response;
        }
    }
}